
#include "EpollDispatcher.h"

EpollDispatcher::EpollDispatcher(EventLoop *eventLoop)
    : Dispatcher(eventLoop) // 这里用的父类的构造函数
{
    this->m_epfd = epoll_create(1);
    // Debug("epoll fd %d",data->epfd);
    if (this->epfd == -1)
    {
        perror("epoll_create");
        exit(0);
    }
    // 采用new的方式初始化
    this->m_events = new struct epoll_event[this->m_maxevents];
    this->m_name = "epoll";
}

int EpollDispatcher::add() override
{
    int ret = epollCtl( EPOLL_CTL_ADD);
    if (ret == -1)
    {
        perror("epoll_ctl");
        exit(0);
    }
    return ret;
}
// 移除 ,把一个节点从epoll树上删除
int EpollDispatcher::remove()
{
    int ret = epollCtl( EPOLL_CTL_DEL);
    if (ret == -1)
    {
        perror("epoll_remove");
        exit(0);
    }
    // 通过channel释放对应的TcpConnection 的资源
    this->m_channel->destoryCallBack(const_cast<void *>(m_channel->getArg()));
    return ret;
}
// 修改把一个节点从epoll树上修改
int EpollDispatcher::modify()
{
    int ret = epollCtl( EPOLL_CTL_MOD);
    if (ret == -1)
    {
        perror("epoll_modify");
        exit(0);
    }
    return ret;
}
// 事件检测 ，检测epoll树上是否有事件发生
int EpollDispatcher::dispatch(int timeout = 2) // 单位秒
{
    int count = epoll_wait(this->m_epfd, this->m_events, m_maxEvents, timeout * 1000); // 传进来的事件是ms

    for (int i = 0; i < count; i++)
    {
        // 注意这是一个一个的
        int events = this->m_events[i].events;
        int fd = this->m_events[i].data.fd;

        // 当对端断开连接  第二个 对端断开连接 然后我们还在给对方发数据
        if (events & EPOLLERR || events & EPOLLHUP)
        {
            // 错误事件
            // 这个channel 后续处理
            // epollRemove(Channel,eventLoop);
            continue;
        }
        if (events & EPOLLIN)
        {
            // 读事件 具体怎么说呢 通过一种映射 fd-> channel* 封装在channelMap 里面  然后channel 里面封装了方法的
            eventActivate(eventLoop, fd, ReadEvent);
        }
        if (events & EPOLLOUT)
        {
            eventActivate(eventLoop, fd, WriteEvent);
        }
    }
    return 0;
}

EpollDispatcher::~EpollDispatcher()
{
    close(this->m_epfd);
    // 定义的是一个数组
    delete[] this->m_events;
}

int EpollDispatcher::epollCtl(int op)
{
    struct epoll_event ev;
    ev.data.fd = m_channel->getSocket();
    int events = 0;
    if (m_channel->getEvent() & static_cast<int>(FDEvent::ReadEvent))
    {
        events |= EPOLLIN;
    }
    if (m_channel->getEvent() & static_cast<int>(FDEvent::WriteEvent))
    {
        events |= EPOLLOUT;
    }
    ev.events = events;
    int ret = epoll_ctl(this->m_epfd, op, this->m_channel->getSocket(), &ev);
    return ret
}
